﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using System.Xml.Serialization;

namespace Tomahawk.Runtime.Rendering.Particles
{
    [XmlInclude(typeof(ParticleSourcePoint))]
    [XmlInclude(typeof(ParticleSourceSegment))]
    [XmlInclude(typeof(ParticleSourceCircle))]
    [XmlInclude(typeof(ParticleSourceRectangle))]
    public abstract class ParticleSource
    {
        // Range of values controlling how much X and Z axis velocity to give each
        // particle. Values for individual particles are randomly chosen from somewhere
        // between these limits.
        [XmlElement("HorizontalVelocityNoise")]
        public Vector2 HorizontalVelocityNoise = Vector2.Zero;

        // Range of values controlling how much Y axis velocity to give each particle.
        // Values for individual particles are randomly chosen from somewhere between
        // these limits.
        [XmlElement("VerticalVelocityNoise")]
        public Vector2 VerticalVelocityNoise = Vector2.Zero;

        // Shared random number generator.
        static Random random = new Random();
        public static Random Random { get { return random; } }

        public abstract Vector3 GenerateParticlePosition(ref Matrix worldMatrix);
        public abstract Vector3 GenerateParticleVelocity(ref Matrix worldMatrix);
        
        protected Vector3 AddNoiseToVelocity(ref Vector3 velocity)
        {
            Vector3 result = Vector3.Zero;

            // Add in some random amount of horizontal velocity.
            float horizontalVelocity = MathHelper.Lerp(HorizontalVelocityNoise.X,
                                                       HorizontalVelocityNoise.Y,
                                                       (float)random.NextDouble());

            double horizontalAngle = random.NextDouble() * MathHelper.TwoPi;

            result.X = velocity.X + horizontalVelocity * (float)Math.Cos(horizontalAngle);
            result.Z = velocity.Z + horizontalVelocity * (float)Math.Sin(horizontalAngle);

            // Add in some random amount of vertical velocity.
            result.Y = velocity.Y + MathHelper.Lerp(VerticalVelocityNoise.X,
                                                    VerticalVelocityNoise.Y,
                                                    (float)random.NextDouble());

            return result;
        }
    }
}
